<template>
  <div class="kpi-bussiness">
    <div class="bussiness-list">
      <div class="table-selecor">
        加工表：
        <el-select v-model="selectTable">
          <el-option label="---" value=""></el-option>
          <el-option
            v-for="item in tableList"
            :key="item.tableNm"
            :label="item.tableNm"
            :value="item.tableNm"
          ></el-option>
        </el-select>
      </div>
      <el-collapse v-model="type" accordion>
        <el-collapse-item name="all" title="全部字段">
          <template v-if="fieldList.length">
            <el-input v-model="keyword" placeholder="搜索字段" clearable></el-input>
            <ul class="field-list tag-scrollbar">
              <li v-for="item in showFieldList" :key="item.fieldNm" draggable @dragstart="copyDrag($event, item)">
                {{ item.fieldNm }}
                <div class="list-handler">
                  <el-tooltip effect="dark" content="添加" placement="top" :enterable="false">
                    <span class="plus" @click.prevent="addItem(item)"><i class="el-icon-plus"></i></span>
                  </el-tooltip>
                </div>
              </li>
            </ul>
          </template>
          <div class="no-record" v-else>
            <template v-if="selectTable">
              <img src="~@/assets/img/no_records.png" /><br />
              暂无内容
            </template>
            <template v-else>
              请先选择加工表
            </template>
          </div>
        </el-collapse-item>
      </el-collapse>
    </div>
    <div class="bussiness-content">
      <div class="header">
        <el-row>
          <el-col :span="6">
            <icon-svg name="iconRole"></icon-svg>
            业务修饰词
          </el-col>
          <el-col :span="18">
            <div class="btns">
              <el-button @click="handleReject">
                <icon-svg name="iconCancel"></icon-svg>
                取消
              </el-button>
              <el-button type="primary" @click="handleSave">
                <icon-svg name="iconSave"></icon-svg>
                保存
              </el-button>
            </div>
          </el-col>
        </el-row>
      </div>
      <el-form :model="editForm" ref="editForm" label-width="0">
        <div class="content list-wrap tag-scrollbar" @drop="copyDrop($event)" @dragover="allowDrag($event)">
          <div class="config-tips" v-if="!editForm.tagConfig.tagList.length">
            <span>
              <i class="el-icon-plus"></i>
            </span>
            <br />
            将字段拖入此区域，添加业务修饰词配置
          </div>
          <div class="ul" v-else>
            <div
              class="logical"
              :class="{ 'logical-or': editForm.tagConfig.logicalOperation === 'or' }"
              v-if="editForm.tagConfig.tagList.length > 1"
            >
              <el-form-item prop="logicalOperation">
                <el-select
                  v-model="editForm.tagConfig.logicalOperation"
                  @click.native="toggleOperation(-1)"
                  disabled
                  popper-class="factory-select"
                  class="default"
                >
                  <el-option label="且" value="and"></el-option>
                  <el-option label="或" value="or"></el-option>
                </el-select>
              </el-form-item>
            </div>
            <div v-for="(item, index) in editForm.tagConfig.tagList" :key="index" class="ul-wrap">
              <!-- 没有下级 -->
              <template v-if="!item.tagList">
                <div class="list-item" :level="1" :fieldNm="item.fieldNm" :index="index">
                  <el-row :gutter="8">
                    <el-col :span="8">
                      <div class="item" align="center" draggable @dragstart="copyDrag($event, item, index)">
                        {{ item.fieldNm }}
                      </div>
                    </el-col>
                    <el-col :span="4" align="center">
                      <div class="item">
                        <el-form-item
                          :prop="'tagConfig.tagList.' + index + '.operationType'"
                          :rules="[
                            {
                              required: true,
                              message: '运算符不能为空',
                              trigger: 'change'
                            }
                          ]"
                        >
                          <el-select v-model="item.operationType" @change="changeType($event, item)">
                            <el-option label="---" value=""></el-option>
                            <el-option
                              v-for="opera in operatorType('type' + item.valueType)"
                              :key="opera.value"
                              :label="opera.key"
                              :value="opera.value"
                            ></el-option>
                          </el-select>
                        </el-form-item>
                      </div>
                    </el-col>
                    <el-col :span="12">
                      <div class="item">
                        <el-form-item
                          :prop="'tagConfig.tagList.' + index + '.operationValue'"
                          :rules="[
                            {
                              required: true,
                              message: '值不能为空',
                              trigger: ['blur', 'change']
                            }
                          ]"
                        >
                          <factory-content-item :config="item"></factory-content-item>
                        </el-form-item>
                      </div>
                    </el-col>
                  </el-row>
                  <el-button
                    type="primary"
                    size="mini"
                    icon="el-icon-close"
                    circle
                    @click="deleteItem(index)"
                  ></el-button>
                </div>
              </template>
              <template v-else>
                <div class="ol" :class="{ space: item.tagList.length > 1 }">
                  <div class="logical" :class="{ 'logical-or': item.logicalOperation === 'or' }">
                    <el-form-item :prop="'tagConfig.tagList.' + index + '.logicalOperation'">
                      <el-select
                        v-model="item.logicalOperation"
                        @click.native="toggleOperation(index)"
                        :level="index"
                        popper-class="factory-select"
                        disabled
                        class="default"
                      >
                        <el-option label="且" value="and"></el-option>
                        <el-option label="或" value="or"></el-option>
                      </el-select>
                    </el-form-item>
                  </div>
                  <div v-for="(child, index2) in item.tagList" :key="index2">
                    <!-- 没有第三层 -->
                    <template v-if="!child.tagList">
                      <div class="list-item" :level="2" :fieldNm="child.fieldNm" :index="index + '-' + index2">
                        <el-row :gutter="8">
                          <el-col :span="8">
                            <div
                              class="item"
                              align="center"
                              draggable
                              @dragstart="copyDrag($event, child, index, index2)"
                            >
                              {{ child.fieldNm }}
                            </div>
                          </el-col>
                          <el-col :span="4" align="center">
                            <div class="item">
                              <el-form-item
                                :prop="'tagConfig.tagList.' + index + '.tagList.' + index2 + '.operationType'"
                                :rules="[
                                  {
                                    required: true,
                                    message: '运算符不能为空',
                                    trigger: 'change'
                                  }
                                ]"
                              >
                                <el-select v-model="child.operationType" @change="changeType($event, child)">
                                  <el-option label="---" value=""></el-option>
                                  <el-option
                                    v-for="opera in operatorType('type' + child.valueType)"
                                    :key="opera.value"
                                    :label="opera.key"
                                    :value="opera.value"
                                  ></el-option>
                                </el-select>
                              </el-form-item>
                            </div>
                          </el-col>
                          <el-col :span="12">
                            <div class="item">
                              <el-form-item
                                :prop="'tagConfig.tagList.' + index + '.tagList.' + index2 + '.operationValue'"
                                :rules="[
                                  {
                                    required: true,
                                    message: '值不能为空',
                                    trigger: ['blur', 'change']
                                  }
                                ]"
                              >
                                <factory-content-item :config="child"></factory-content-item>
                              </el-form-item>
                            </div>
                          </el-col>
                        </el-row>
                        <el-button
                          type="primary"
                          size="mini"
                          icon="el-icon-close"
                          circle
                          @click="deleteItem(index, index2)"
                        ></el-button>
                      </div>
                    </template>
                    <div class="ol space" v-else>
                      <!-- 第三层的逻辑符号 -->
                      <div class="logical" :class="{ 'logical-or': child.logicalOperation === 'or' }">
                        <el-form-item :prop="'tagConfig.tagList.' + index + '.tagList.' + index2 + '.logicalOperation'">
                          <el-select
                            v-model="child.logicalOperation"
                            @click.native="toggleOperation(index, index2)"
                            :level="index + '-' + index2"
                            popper-class="factory-select"
                            disabled
                            class="default"
                          >
                            <el-option label="且" value="and"></el-option>
                            <el-option label="或" value="or"></el-option>
                          </el-select>
                        </el-form-item>
                      </div>
                      <div v-for="(third, index3) in child.tagList" :key="index3">
                        <div
                          class="list-item"
                          :level="3"
                          :fieldNm="third.fieldNm"
                          :index="index + '-' + index2 + '-' + index3"
                        >
                          <el-row :gutter="8">
                            <el-col :span="8">
                              <div
                                class="item"
                                align="center"
                                draggable
                                @dragstart="copyDrag($event, third, index, index2, index3)"
                              >
                                {{ third.fieldNm }}
                              </div>
                            </el-col>
                            <el-col :span="4" align="center">
                              <div class="item">
                                <el-form-item
                                  :prop="
                                    'tagConfig.tagList.' +
                                      index +
                                      '.tagList.' +
                                      index2 +
                                      '.tagList.' +
                                      index3 +
                                      '.operationType'
                                  "
                                  :rules="[
                                    {
                                      required: true,
                                      message: '运算符不能为空',
                                      trigger: 'change'
                                    }
                                  ]"
                                >
                                  <el-select v-model="third.operationType" @change="changeType($event, third)">
                                    <el-option label="---" value=""></el-option>
                                    <el-option
                                      v-for="opera in operatorType('type' + third.valueType)"
                                      :key="opera.value"
                                      :label="opera.key"
                                      :value="opera.value"
                                    ></el-option>
                                  </el-select>
                                </el-form-item>
                              </div>
                            </el-col>
                            <el-col :span="12">
                              <div class="item">
                                <el-form-item
                                  :prop="
                                    'tagConfig.tagList.' +
                                      index +
                                      '.tagList.' +
                                      index2 +
                                      '.tagList.' +
                                      index3 +
                                      '.operationValue'
                                  "
                                  :rules="[
                                    {
                                      required: true,
                                      message: '值不能为空',
                                      trigger: ['blur', 'change']
                                    }
                                  ]"
                                >
                                  <factory-content-item :config="third"></factory-content-item>
                                </el-form-item>
                              </div>
                            </el-col>
                          </el-row>
                          <el-button
                            type="primary"
                            size="mini"
                            icon="el-icon-close"
                            circle
                            @click="deleteItem(index, index2, index3)"
                          ></el-button>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </template>
            </div>
          </div>
        </div>
      </el-form>
    </div>
    <bussiness-config-drawer ref="bussinessConfigDrawer" @confirm="handleSubmit"></bussiness-config-drawer>
  </div>
</template>

<script>
import operator from '../../factory/operator'
import factoryContentItem from '../../factory/factory-content-item'
import bussinessConfigDrawer from './bussiness-edit-item'
import bussunessConfig from './bussiness-config.js'
import cloneDeep from 'lodash/cloneDeep'
export default {
  components: {
    factoryContentItem,
    bussinessConfigDrawer
  },
  data() {
    return {
      table: '',
      type: 'all',
      tableList: [],
      fieldList: [],
      keyword: '',
      selectTable: '',
      oldConfig: {},
      editForm: {
        tagId: '',
        businessName: '',
        description: '',
        tagConfig: {
          logicalOperation: 'and',
          tagList: []
        }
      }
    }
  },
  created() {
    this.getTable().then(() => {
      if (this.$route.query.tagId) {
        this.editForm.tagId = this.$route.query.tagId
        this.getDetail()
      }
    })
  },
  computed: {
    showFieldList() {
      return this.keyword.trim()
        ? this.fieldList.filter(item => item.fieldNm.indexOf(this.keyword.trim()) >= 0)
        : this.fieldList
    }
  },
  watch: {
    selectTable() {
      this.keyword = ''
      this.getFieldList()
    }
  },
  methods: {
    getDetail() {
      this.$ajax({
        url: this.$ajax.setUrl(`IndexAllocation/getIndexAllocation/${this.editForm.tagId}`),
        method: 'get',
        params: this.$ajax.setParams()
      }).then(({ data }) => {
        if (data && data.code === '0') {
          const config = JSON.parse(data.data.indexJson)
          this.editForm.businessName = config.businessName
          this.editForm.description = config.description
          this.selectTable = config.tagConfig.request.labGrps.labs[0].labTbl
            ? config.tagConfig.request.labGrps.labs[0].labTbl.split('.')[1]
            : config.tagConfig.request.labGrps.labs[0].labs[0].labTbl
            ? config.tagConfig.request.labGrps.labs[0].labs[0].labTbl.split('.')[1]
            : config.tagConfig.request.labGrps.labs[0].labs[0].labs.labTbl.split('.'[1])
          this.editForm.tagConfig.logicalOperation = config.tagConfig.request.labGrps.logicTyp
          this.editForm.tagConfig.tagList = bussunessConfig.initLogic(config.tagConfig.request.labGrps.labs)
          this.oldConfig = cloneDeep(this.editForm)
        } else {
          this.$message.error(data.data || data.msg)
        }
      })
    },
    operatorType(key) {
      return operator[key]
    },
    changeType(type, item) {
      if (item.valueType == '4' || item.valueType == '5') {
        if (type === 'a<=x<b') item.operationValue = []
        else if (type === 8 || type === 9) item.operationValue = [1, '1']
        else item.operationValue = ''
      } else if (item.valueType == '6') {
        if (type === 'a<=x<b') item.operationValue = [1, 1]
        else item.operationValue = ''
      } else if (item.valueType == '7') {
        if (type === 'a<=x<b') item.operationValue = [1.0, 1.0]
        else item.operationValue = ''
      } else {
        item.operationValue = ''
      }
    },
    getTable() {
      return new Promise((resolve, reject) => {
        this.$ajax({
          url: this.$ajax.setUrl('der/derKpiType/getAllTable'),
          method: 'get',
          params: this.$ajax.setParams()
        }).then(({ data }) => {
          if (data && data.code === '0') {
            this.tableList = data.data
            resolve()
          } else {
            this.$message.error(data.data || data.msg)
            reject()
          }
        })
      })
    },
    getFieldList() {
      const tableItem = this.tableList.find(item => item.tableNm === this.selectTable)
      this.$ajax({
        url: this.$ajax.setUrl('der/derKpiType/getTableFields'),
        method: 'post',
        data: this.$ajax.setData({
          dbName: tableItem.dbName,
          plfmId: tableItem.plfmId,
          relaField: tableItem.relaField,
          tableNm: tableItem.tableNm,
          tableType: tableItem.tableType
        })
      }).then(({ data }) => {
        if (data && data.code === '0') {
          this.fieldList = data.data
        } else {
          this.$message.error(data.data || data.msg)
        }
      })
    },
    addItem(item) {
      const target = this.tableList.find(table => table.tableNm === this.selectTable)
      this.editForm.tagConfig.tagList.push({
        tableNm: `${target.dbName}.${item.tableNm}`,
        fieldNm: item.fieldNm,
        valueType: item.valueType,
        datTyp: this.$dictDb('value_type')[item.valueType],
        operationType: '',
        operationValue: ''
      })
    },
    copyDrag(event, item, index = -1, index2 = -1, index3 = -1) {
      if (!item.fieldNm) return
      const target = this.tableList.find(table => table.tableNm === this.selectTable)
      event.dataTransfer.setData('tableNm', `${target.dbName}.${item.tableNm}`)
      event.dataTransfer.setData('fieldNm', item.fieldNm)
      event.dataTransfer.setData('valueType', item.valueType)
      event.dataTransfer.setData('datTyp', this.$dictDb('value_type')[item.valueType])
      event.dataTransfer.setData('operationType', item.operationType || '')
      event.dataTransfer.setData('operationValue', item.operationValue ? JSON.stringify(item.operationValue) : '')
      if (index >= 0) {
        event.dataTransfer.setData('config', JSON.stringify(Object.assign({}, item, { index, index2, index3 })))
        event.dataTransfer.setData('clientY', event.clientY)
      }
    },
    allowDrag(event) {
      event.preventDefault()
    },
    copyDrop(event) {
      // 判断拖动的高度小于50则不改变
      if (event.dataTransfer.getData('clientY')) {
        let clientY = event.dataTransfer.getData('clientY')
        if (Math.abs(event.clientY - clientY) < 50) return
      }
      let isConfig = event.dataTransfer.getData('config')
      event.preventDefault()
      let fieldNm = event.dataTransfer.getData('fieldNm')
      if (!fieldNm) return
      let content = this.editForm.tagConfig.tagList
      let tableNm = event.dataTransfer.getData('tableNm')
      let valueType = event.dataTransfer.getData('valueType')
      let datTyp = event.dataTransfer.getData('datTyp')
      let operationType = event.dataTransfer.getData('operationType')
      let operationValue = event.dataTransfer.getData('operationValue').length
        ? JSON.parse(event.dataTransfer.getData('operationValue'))
        : event.dataTransfer.getData('operationValue')
      let arg = {
        tableNm,
        fieldNm,
        valueType,
        datTyp,
        operationType,
        operationValue
      }
      if (
        this.editForm.tagConfig.tagList.length < 2 ||
        event.target.className.split(' ').find(item => item === 'list-wrap')
      ) {
        if (!this.editForm.tagConfig.tagList.length) this.editForm.tagConfig.logicalOperation = 'and'
        this.editForm.tagConfig.tagList.push(arg)
      } else {
        let nodes = []
        let target = event.target
        if (target.className.includes('el-input__inner')) {
          // 拖到逻辑条件处，直接添加
          const targetLevel = target.parentNode.parentNode.getAttribute('level')
          if (!targetLevel) this.editForm.tagConfig.tagList.push(arg)
          else if (targetLevel.indexOf('-') > -1) {
            // 第三层
            const level1 = targetLevel.split('-')[0]
            const level2 = targetLevel.split('-')[1]
            this.editForm.tagConfig.tagList[level1].tagList[level2].tagList.push(arg)
          } else {
            this.editForm.tagConfig.tagList[targetLevel].tagList.push(arg)
          }
        } else {
          while (target.className !== 'ul') {
            nodes.push(target)
            target = target.parentNode
          }
          const li = nodes.find(item => item.className === 'list-item')
          if (!li) return
          const targetLevel = parseInt(li.getAttribute('level'))
          const targetFieldNm = li.getAttribute('fieldNm')
          if (targetLevel === 1) {
            // 拖到第一层，一起掉到第二层
            const index = Number(li.getAttribute('index'))
            for (let i = 0; i < content.length; i++) {
              if (content[i].fieldNm === targetFieldNm && i === index) {
                const old_content = content[i]
                this.$set(content, i, {
                  logicalOperation: 'and',
                  tagList: [old_content, arg]
                })
              }
            }
          } else if (targetLevel === 2) {
            // 拖到第二层，一起掉到第三层
            const index = li.getAttribute('index')
            const index1 = index.split('-')[0]
            const index2 = index.split('-')[1]
            const old_content = content[index1].tagList[index2]
            this.$set(content[index1].tagList, index2, {
              logicalOperation: 'and',
              tagList: [old_content, arg]
            })
          } else {
            const index = li.getAttribute('index')
            const index1 = index.split('-')[0]
            const index2 = index.split('-')[1]
            const index3 = index.split('-')[2]
            content[index1].tagList[index2].tagList.splice(index3 + 1, 0, arg)
          }
        }
      }
      if (isConfig) {
        // 右侧拖动，删除原来的数据源
        let config = JSON.parse(isConfig)
        this.deleteItem(config.index, config.index2, config.index3)
        // 将子元素插入到原来图层
        if (config.derivedTag && config.derivedTag.tagList.length) {
          content.splice(config.index, 0, ...config.derivedTag.tagList)
        }
      }
      this.$forceUpdate()
    },
    deleteItem(index = -1, index2 = -1, index3 = -1) {
      if (index3 >= 0) {
        this.editForm.tagConfig.tagList[index].tagList[index2].tagList.splice(index3, 1)
        // 如果只剩一条，则提升到第二层
        if (this.editForm.tagConfig.tagList[index].tagList[index2].tagList.length < 2) {
          const content = this.editForm.tagConfig.tagList[index].tagList[index2].tagList[0]
          this.editForm.tagConfig.tagList[index].tagList.splice(index2, 1, content)
        }
      } else {
        if (index2 >= 0) {
          this.editForm.tagConfig.tagList[index].tagList.splice(index2, 1)
          // 如果只剩一条，则提升到第一层
          if (this.editForm.tagConfig.tagList[index].tagList.length < 2) {
            const content = this.editForm.tagConfig.tagList[index].tagList[0]
            this.editForm.tagConfig.tagList.splice(index, 1, content)
          }
        } else {
          this.editForm.tagConfig.tagList.splice(index, 1)
          // 如果只剩一条合并数据，则提升到第一层
          if (this.editForm.tagConfig.tagList.length && this.editForm.tagConfig.tagList.length < 2) {
            const content = this.editForm.tagConfig.tagList[0]
            if (!content.fieldNm) {
              this.editForm.tagConfig.logicalOperation = content.logicalOperation
              this.editForm.tagConfig.tagList = content.tagList
            }
          }
        }
      }
    },
    toggleOperation(index, index2 = -1) {
      if (index < 0) {
        this.editForm.tagConfig.logicalOperation = this.editForm.tagConfig.logicalOperation === 'and' ? 'or' : 'and'
      } else {
        if (index2 < 0) {
          const operation = this.editForm.tagConfig.tagList[index].logicalOperation
          this.editForm.tagConfig.tagList[index].logicalOperation = operation === 'and' ? 'or' : 'and'
        } else {
          const operation = this.editForm.tagConfig.tagList[index].tagList[index2].logicalOperation
          this.editForm.tagConfig.tagList[index].tagList[index2].logicalOperation = operation === 'and' ? 'or' : 'and'
        }
      }
    },
    handleSave() {
      this.$refs.editForm.validate(valid => {
        if (valid) {
          this.$refs.bussinessConfigDrawer.showDrawer({
            businessName: this.editForm.businessName,
            description: this.editForm.description
          })
        }
      })
    },
    handleSubmit(data) {
      this.editForm.businessName = data.businessName
      this.editForm.description = data.description
      let config = {
        businessName: this.editForm.businessName,
        description: this.editForm.description,
        tableName: this.selectTable,
        tagConfig: bussunessConfig.initParams(this.editForm.tagConfig)
      }
      let params = {
        indexType: 2,
        indexJson: JSON.stringify(config)
      }
      if (this.editForm.tagId) params.tagId = this.editForm.tagId
      this.$ajax({
        url: this.$ajax.setUrl('IndexAllocation/addIndexConfig'),
        method: 'post',
        data: this.$ajax.setData(params)
      }).then(({ data }) => {
        if (data && data.code === '0') {
          this.$refs.bussinessConfigDrawer.drawerVisible = false
          this.oldConfig = cloneDeep(this.editForm.tagConfig)
          this.$message({
            message: data.msg,
            type: 'success',
            duration: 1000,
            onClose: () => {
              this.$router.replace({ name: 'kpi-params', query: { tabName: 'bussiness' } })
            }
          })
        } else {
          this.$message.error(data.data || data.msg)
        }
      })
    },
    handleReject() {
      this.$confirm('确定取消最新的编辑？').then(() => {
        const config = cloneDeep(this.oldConfig)
        if (config.tagId) {
          this.editForm.businessName = config.businessName
          this.editForm.description = config.description
          this.editForm.tagConfig = config.tagConfig
        } else {
          this.editForm.businessName = ''
          this.editForm.description = ''
          this.editForm.tagConfig = {
            logicalOperation: 'and',
            tagList: []
          }
        }
      })
    }
  }
}
</script>

<style lang="scss">
@import './bussiness-config.scss';
</style>
